<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;

class GenerateInsights extends Command
{
    protected $signature = 'generate:insights';
    protected $description = 'Generate insights from Reddit search (batched 20 per round)';

    /** @var Client */
    protected $http;

    public function __construct()
    {
        parent::__construct();

        // 初始化 Guzzle（匿名搜索也需要一个明确的 User-Agent）
        $this->http = new Client([
            'timeout' => 20,
            'headers' => [
                'User-Agent' => 'LaravelRedditInsights/0.1 by your_reddit_username'
            ]
        ]);
    }

    public function handle(): int
    {
        // ① 载体（精简版）
        $anchors = [
            "chrome extension",
            "browser extension",
            "firefox add-on",
            "edge extension",
            "plugin",
            "add-on",   // 将自动扩展出 "addon"
            "userscript",
            "tampermonkey",
            "greasemonkey",
            "web app",
            "web tool",
            "online tool"
        ];

        // ② 动词（动作）
        $verbs = [
            "automate", "automation", "bulk", "batch",
            "export", "import", "extract", "scrape", "parse",
            "summarize", "summarise", "highlight", "compare",
            "merge", "dedupe", "deduplicate", "clean", "normalize",
            "reformat", "convert", "rename", "generate",
            "autofill", "prefill", "template", "snippet",
            "shortcut", "macro", "schedule", "monitor",
            "alert", "webhook", "api", "csv", "copy to clipboard"
        ];

        // ③ 意图（不是载体，只与 verbs 组合）
        $intents = [
            "one click",
            "one-click",
            "with one click",
            "single click"
        ];

        // 可选：pain terms（当需要更严格的提纯时再与查询做 AND 组合）
        $pain_terms = [
            "annoying", "frustrating", "tedious", "repetitive", "manual",
            "time-consuming", "too many clicks", "takes forever", "error-prone",
            "cumbersome", "clunky", "slow", "too slow", "hard to maintain"
        ];

        // 1) 扩展锚点变体（"add-on" => "addon"）
        $anchors = $this->expandAnchors($anchors);

        // 2) 生成查询池
        // 2.1 载体 × 动词（先用宽松版；噪音多时切换 strict）
        $queries_vehicle_loose  = $this->buildQueries($anchors, $verbs, false, false);
        // $queries_vehicle_strict = $this->buildQueries($anchors, $verbs, true,  false);
        // $queries_vehicle_title  = $this->buildQueries($anchors, $verbs, true,  true); // 只在标题匹配载体，进一步提纯

        // 2.2 意图 × 动词（one click 家族）
        $queries_intent_loose   = $this->buildQueries($intents, $verbs, false, false);
        // $queries_intent_strict  = $this->buildQueries($intents, $verbs, true,  false);

        // 2.3 合并并去重（当前启用：载体宽松 + 意图宽松）
        $queries = array_values(array_unique(array_merge(
            $queries_vehicle_loose,
            $queries_intent_loose
        )));

        // （可选）更严格：在严格版基础上与 pain 做 AND 提纯
        // $queries_strict = array_merge($queries_vehicle_strict, $queries_intent_strict);
        // $queries = $this->addPainAND($queries_strict, $pain_terms);

        // 3) 将查询池按 20 条一组分批调用
        $batchSize  = 20;
        $maxPages   = 2;   // 每个查询最多翻几页（每页 limit=100）
        $sleepMs    = 300; // 每次请求间隔（毫秒）

        $batches = array_chunk($queries, $batchSize);
        $this->info("Total queries: " . count($queries) . " | Batches: " . count($batches));

        foreach ($batches as $bi => $batch) {
            $this->line("── Batch " . ($bi + 1) . " / " . count($batches) . " (size=" . count($batch) . ")");

            foreach ($batch as $qi => $q) {
                // 分页抓取（每个查询最多 maxPages 页）
                $after = null;
                for ($page = 1; $page <= $maxPages; $page++) {
                    $url = $this->redditSearchUrl($q, [
                        'sort'     => 'new',
                        't'        => 'year',
                        'limit'    => 100,
                        'raw_json' => 1,
                        'type'     => 'link',
                        'after'    => $after
                    ], true /* OAuth? */);

                    try {
                        $resp = $this->http->get($url);
                        $code = $resp->getStatusCode();

                        if ($code === 200) {
                            $json  = json_decode((string) $resp->getBody(), true);
                            $count = $this->handleSearchResponse($q, $json);
                            $this->line(sprintf("  [%02d.%02d] q=\"%s\" | page=%d | hits=%d",
                                $bi + 1, $qi + 1, $q, $page, $count
                            ));

                            // 取分页游标
                            $after = $json['data']['after'] ?? null;
                            if (!$after) {
                                break; // 没有更多页
                            }
                        } else {
                            $this->warn("  HTTP $code for query: $q");
                            break;
                        }
                    } catch (RequestException $e) {
                        $status = $e->getResponse() ? $e->getResponse()->getStatusCode() : null;
                        $this->warn("  RequestException (status=$status) for query: $q");
                        // 简单退避：429/5xx 时稍作等待
                        if (in_array($status, [429, 500, 502, 503, 504], true)) {
                            usleep(1500 * 1000); // 1.5s
                        }
                        break; // 当前查询跳出分页循环
                    }

                    // 每次请求间隔
                    usleep($sleepMs * 1000);
                }
            }

            // 批次间隔（可根据需要调整/删除）
            usleep(1000 * 1000); // 1s
        }

        return Command::SUCCESS;
    }

    /**
     * 处理搜索响应：在此解析/入库/派发队列
     */
    protected function handleSearchResponse(string $query, array $json): int
    {
        if (!isset($json['data']['children']) || !is_array($json['data']['children'])) {
            return 0;
        }

        $hits = $json['data']['children'];

        // TODO: 在这里把每条帖子存入 posts 表；也可以先做去重（simhash/digest）后再入库
        // foreach ($hits as $item) {
        //     $data = $item['data'] ?? [];
        //     // 取 id、title、selftext、subreddit、score、num_comments、created_utc、permalink 等
        //     // Post::updateOrCreate([...]);
        // }

        return count($hits);
    }

    /**
     * 载体/意图 × 动词
     * $strict=false：宽松（空格连接，默认“部分匹配”）
     * $strict=true ：严格（AND 连接，约束更强）
     * $titleOnly=true：对 Left 加 title: 限定（只在标题匹配载体/意图）
     */
    protected function buildQueries(array $left, array $verbs, bool $strict = false, bool $titleOnly = false): array
    {
        $out = [];
        foreach ($left as $L) {
            $Lq = $this->q($L);
            if ($titleOnly) {
                $Lq = 'title:' . $Lq; // 只在标题里要求出现
            }
            foreach ($verbs as $v) {
                $Vq = $this->q($v);
                $out[] = $strict ? ($Lq . ' AND ' . $Vq) : ($Lq . ' ' . $Vq);
            }
        }
        return array_values(array_unique($out));
    }

    /**
     * 在查询基础上，与 pain_terms 做 AND 提纯（可选）
     * 例如：("chrome extension" AND summarize) AND "too many clicks"
     */
    protected function addPainAND(array $queries, array $pain_terms): array
    {
        if (empty($pain_terms)) return $queries;
        $out = [];
        foreach ($queries as $q) {
            foreach ($pain_terms as $p) {
                $out[] = $q . ' AND ' . $this->q($p);
            }
        }
        return $out;
    }

    /**
     * 生成 Reddit 搜索 URL（OAuth 或匿名）
     */
    protected function redditSearchUrl(string $q, array $params = [], bool $oauth = false): string
    {
        $base = $oauth ? 'https://oauth.reddit.com/search' : 'https://www.reddit.com/search.json';

        $defaults = [
            'q'        => $q,
            'sort'     => 'new',
            't'        => 'year',
            'limit'    => 100,
            'raw_json' => 1,
            'type'     => 'link',
        ];

        $query = http_build_query(array_merge($defaults, $params));
        return $base . '?' . $query;
    }

    /**
     * 带空格的短语加双引号，用于短语匹配
     */
    protected function q(string $term): string
    {
        $t = trim($term);
        return (strpos($t, ' ') !== false) ? '"' . $t . '"' : $t;
    }

    /**
     * 扩展锚点：把 "add-on" 自动补充为 "addon" 变体
     */
    protected function expandAnchors(array $anchors): array
    {
        $extra = [];
        foreach ($anchors as $a) {
            if (mb_strtolower($a, 'UTF-8') === 'add-on') {
                $extra[] = 'addon';
            }
        }
        return array_values(array_unique(array_merge($anchors, $extra)));
    }
}
